package com.hh.service.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hh.common.constants.Constants;
import com.hh.common.exception.HhException;
import com.hh.common.model.order.OrderLogisticsTrack;
import com.hh.common.response.LogisticsQueryResponse;
import com.hh.common.utils.*;
import com.hh.common.vo.*;
import com.hh.service.dao.OrderLogisticsTrackDao;
import com.hh.service.dao.StoreOrderDao;
import com.hh.service.dao.integral.IntegralOrderDao;
import com.hh.service.service.LogisticService;
import com.hh.service.service.OnePassService;
import com.hh.service.service.SystemConfigService;
import com.kuaidi100.sdk.api.QueryTrack;
import com.kuaidi100.sdk.core.IBaseClient;
import com.kuaidi100.sdk.pojo.HttpResult;
import com.kuaidi100.sdk.request.QueryTrackParam;
import com.kuaidi100.sdk.request.QueryTrackReq;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
* ExpressServiceImpl 接口实现
*  +----------------------------------------------------------------------
 *  | hh [ hh赋能开发者，助力企业发展 ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2016~2022 https://www.hh.com All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed hh并不是自由软件，未经许可不能去掉hh相关版权
 *  +----------------------------------------------------------------------
 *  | Author: hh Team <admin@hh.com>
 *  +----------------------------------------------------------------------
*/
@Data
@Service
public class LogisticsServiceImpl implements LogisticService {
    //快递查询KEY
    private static final String QUERYKEY_PREFIX = "LOGISTICS_QUERY_CACHE_KEY:";

    @Resource
    private OrderLogisticsTrackDao orderLogisticsTrackDao;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private RestTemplateUtil restTemplateUtil;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private OnePassService onePassService;

    @Resource
    private StoreOrderDao storeOrderDao;

    @Resource
    private IntegralOrderDao integralOrderDao;

    private String redisKey = Constants.LOGISTICS_KEY;
    private Long redisCacheSeconds = 1800L;

    private String expressNo;


    /** 快递
     * @param expressNo String 物流单号
     * @param type String 快递公司字母简写：不知道可不填 95%能自动识别，填写查询速度会更快 https://market.aliyun.com/products/56928004/cmapi021863.html#sku=yuncode15863000015
     * @param com 快递公司编号
     * @author Mr.Zhang
     * @since 2020-06-10
     * @return Express
     */
    @Override
    public LogisticsResultVo info(String expressNo, String type, String com, String phone) {
        LogisticsResultVo resultVo = new LogisticsResultVo();
        setExpressNo(expressNo);
        JSONObject result = getCache();
        if (ObjectUtil.isNotNull(result)) {
            return JSONObject.toJavaObject(result, LogisticsResultVo.class);
        }
        String logisticsType = systemConfigService.getValueByKeyException("logistics_type",false,Constants.PLATFORM_MER_ID);
        if (logisticsType.equals("1")) {// 平台查询
            OnePassLogisticsQueryVo queryVo = onePassService.exprQuery(expressNo, com);
            if (ObjectUtil.isNull(queryVo)) {
                return resultVo;
            }
            // 一号通vo转公共返回vo
            resultVo = queryToResultVo(queryVo);
            String jsonString = JSONObject.toJSONString(resultVo);
            saveCache(JSONObject.parseObject(jsonString));
        }
        if (logisticsType.equals("2")) {// 阿里云查询
            String appCode = systemConfigService.getValueByKey(Constants.CONFIG_KEY_LOGISTICS_APP_CODE,false,Constants.PLATFORM_MER_ID);

            // 顺丰请输入单号 : 收件人或寄件人手机号后四位。例如：123456789:1234
            if (StrUtil.isNotBlank(com) && com.equals("shunfengkuaiyun")) {
                expressNo = expressNo.concat(":").concat(StrUtil.sub(phone, 7, -1));
            }
            String url = Constants.LOGISTICS_API_URL + "?no=" + expressNo;
            if(StringUtils.isNotBlank(type)){
                url += "&type=" + type;
            }

            HashMap<String, String> header = new HashMap<>();
            header.put("Authorization", "APPCODE " + appCode);

            JSONObject data = restTemplateUtil.getData(url, header);
            checkResult(data);
            //把数据解析成对象返回到前端
            result = data.getJSONObject("result");
            saveCache(result);
            resultVo = JSONObject.toJavaObject(result, LogisticsResultVo.class);
        }
        return resultVo;
    }

    /**
     * 快递100物流查询
     * @param orderNo
     * @param deliveryId
     * @return
     */
    @Override
    public LogisticsQueryResponse logisticsQuery(Integer orderType,String orderNo, String deliveryId) {
        String queryKey = QUERYKEY_PREFIX + deliveryId;
        Object o = this.redisUtil.get(queryKey);
        OrderLogisticsTrack orderLogisticsTrack = this.orderLogisticsTrackDao.getLogisticsByDeliveryId(deliveryId);
        OrderLogisticsQueryVo orderLogisticsQueryVo = null;
        if (ObjectUtil.isNull(orderLogisticsTrack)) {
            if(orderType == 1){
                orderLogisticsQueryVo = this.storeOrderDao.logisticsQuery(orderNo);
                if (ObjectUtil.isNull(orderLogisticsQueryVo) || !deliveryId.equals(orderLogisticsQueryVo.getDeliveryId()) || orderLogisticsQueryVo.getStatus() == 0) {
                    throw new HhException("查询不到物流信息~");
                }
            }else{
                orderLogisticsQueryVo = this.integralOrderDao.logisticsQuery(orderNo);
                if (ObjectUtil.isNull(orderLogisticsQueryVo) || !deliveryId.equals(orderLogisticsQueryVo.getDeliveryId()) || orderLogisticsQueryVo.getStatus() == 0) {
                    throw new HhException("查询不到物流信息~");
                }
            }

        }
        if (ObjectUtil.isNotNull(o)) {
            //注意：请控制每一单查询频率至少在半小时以上，否则会造成锁单。
            if (ObjectUtil.isNull(orderLogisticsTrack)) {
                throw new HhException("暂无物流信息，请稍后再试~");
            }
            List<QueryTrackDataVo> queryTrackDataVos = JSONArray.parseArray(orderLogisticsTrack.getDataContext(), QueryTrackDataVo.class);
            if (queryTrackDataVos.size() < 1) {
                throw new HhException("暂无物流信息，请稍后再试~");
            }
            LogisticsQueryResponse logisticsQueryResponse = new LogisticsQueryResponse();
            BeanUtil.copyProperties(orderLogisticsTrack, logisticsQueryResponse);
            logisticsQueryResponse.setUserPhone(HhUtil.maskMobile(logisticsQueryResponse.getUserPhone()));
            logisticsQueryResponse.setTrackInfo(queryTrackDataVos);
            logisticsQueryResponse.setStateStr(queryTrackDataVos.get(0).getStatus());
            return logisticsQueryResponse;
        } else {
            return this.logisticsQueryDo(deliveryId, orderLogisticsTrack, orderLogisticsQueryVo);
        }
    }

    private LogisticsQueryResponse logisticsQueryDo(String deliveryId, OrderLogisticsTrack orderLogisticsTrack, OrderLogisticsQueryVo orderLogisticsQueryVo) {
        String Com;
        String Num;
        if (orderLogisticsTrack == null) {
            Com = orderLogisticsQueryVo.getDeliveryCode();
            Num = orderLogisticsQueryVo.getDeliveryId();
        } else {
            Com = orderLogisticsTrack.getDeliveryCode();
            Num = orderLogisticsTrack.getDeliveryId();
        }
        String queryKey = QUERYKEY_PREFIX + deliveryId;
        QueryTrackReq queryTrackReq = new QueryTrackReq();
        QueryTrackParam queryTrackParam = new QueryTrackParam();
        queryTrackParam.setCom(Com);
        queryTrackParam.setNum(Num);
        queryTrackParam.setResultv2("1");
        String param = JSON.toJSONString(queryTrackParam);
        String customer = this.systemConfigService.getValueByKey(Constants.CONFIG_CUSTOMER_LOGISTICS,false,Constants.PLATFORM_MER_ID);
        String key = this.systemConfigService.getValueByKey(Constants.CONFIG_KEY_LOGISTICS,false,Constants.PLATFORM_MER_ID);
        queryTrackReq.setParam(param);
        queryTrackReq.setCustomer(customer);
        queryTrackReq.setSign(SignUtils.querySign(param, key, customer));

        IBaseClient baseClient = new QueryTrack();
        try {
            HttpResult execute = baseClient.execute(queryTrackReq);
            System.out.println(execute);
            String body = execute.getBody();
            if ((execute.getStatus() == HttpStatus.SC_OK && StringUtils.isNotBlank(body))) {
                LogisticsQueryVo logisticsQueryVo = JSONObject.parseObject(body, LogisticsQueryVo.class);


                List<QueryTrackDataVo> dataList = logisticsQueryVo.getData();
                if (dataList.size() < 1) {
                    throw new HhException("暂无物流信息，请稍后再试~");
                }
                for (QueryTrackDataVo queryTrackDataVo : dataList) {
                    queryTrackDataVo.setBriefTime(this.getBriefTime(queryTrackDataVo.getFtime()));
                }
                String dataContext = JSONObject.toJSONString(dataList);
                String deliveryName;
                String userAddress;
                String userPhone;
                if (orderLogisticsTrack == null) {
                    deliveryName = orderLogisticsQueryVo.getDeliveryName();
                    userAddress = orderLogisticsQueryVo.getUserAddress();
                    userPhone = orderLogisticsQueryVo.getUserPhone();
                    OrderLogisticsTrack orderLogisticsTrack1 = new OrderLogisticsTrack();
                    orderLogisticsTrack1.setOrderId(orderLogisticsQueryVo.getOrderId());
                    orderLogisticsTrack1.setDeliveryCode(orderLogisticsQueryVo.getDeliveryCode());
                    orderLogisticsTrack1.setDeliveryId(orderLogisticsQueryVo.getDeliveryId());
                    orderLogisticsTrack1.setDeliveryName(orderLogisticsQueryVo.getDeliveryName());
                    orderLogisticsTrack1.setState(logisticsQueryVo.getState());
                    orderLogisticsTrack1.setUserAddress(userAddress);
                    orderLogisticsTrack1.setUserPhone(userPhone);
                    orderLogisticsTrack1.setDataContext(dataContext);
                    this.orderLogisticsTrackDao.insert(orderLogisticsTrack1);
                } else {
                    deliveryName = orderLogisticsTrack.getDeliveryName();
                    userAddress = orderLogisticsTrack.getUserAddress();
                    userPhone = orderLogisticsTrack.getUserPhone();
                    orderLogisticsTrack.setState(logisticsQueryVo.getState());
                    orderLogisticsTrack.setDataContext(dataContext);
                    this.orderLogisticsTrackDao.updateById(orderLogisticsTrack);
                }
                LogisticsQueryResponse logisticsQueryResponse = new LogisticsQueryResponse();
                logisticsQueryResponse.setUserAddress(userAddress);
                logisticsQueryResponse.setUserPhone(HhUtil.maskMobile(userPhone));
                logisticsQueryResponse.setDeliveryId(deliveryId);
                logisticsQueryResponse.setDeliveryName(deliveryName);
                logisticsQueryResponse.setState(logisticsQueryVo.getState());
                logisticsQueryResponse.setTrackInfo(dataList);
                logisticsQueryResponse.setStateStr(dataList.get(0).getStatus());
                return logisticsQueryResponse;
            } else {
                throw new HhException("查询失败，请稍后再试！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new HhException("暂无物流轨迹信息");
        } finally {
            this.redisUtil.set(queryKey, "1", this.getRedisCacheSeconds(), TimeUnit.SECONDS);
        }
    }

    private String getBriefTime(String ftime) {
        return DateUtil.formatDateTime(ftime.substring(0, 16));
    }

    /**
     * 一号通vo转公共返回vo
     */
    private LogisticsResultVo queryToResultVo(OnePassLogisticsQueryVo queryVo) {
        LogisticsResultVo resultVo = new LogisticsResultVo();
        resultVo.setNumber(queryVo.getNum());
        resultVo.setExpName(queryVo.getCom());
        resultVo.setIsSign(queryVo.getIscheck());
        resultVo.setDeliveryStatus(queryVo.getStatus());

        if (CollUtil.isNotEmpty(queryVo.getContent())) {
            List<LogisticsResultListVo> list = CollUtil.newArrayList();
            queryVo.getContent().forEach(i -> {
                LogisticsResultListVo listVo = new LogisticsResultListVo();
                listVo.setTime(i.getTime());
                listVo.setStatus(i.getStatus());
                list.add(listVo);
            });
            resultVo.setList(list);
        }
        return resultVo;
    }

    /** 获取快递缓存
     * @author Mr.Zhang
     * @since 2020-07-06
     * @return JSONObject
     */
    private JSONObject getCache() {
        Object data = redisUtil.get(getRedisKey() + getExpressNo());
        if(null != data){
         return JSONObject.parseObject(data.toString());
        }
        return null;
    }

    /** 获取快递缓存
     * @param data JSONObject 需要保存的数据
     * @author Mr.Zhang
     * @since 2020-07-06
     */
    private void saveCache(JSONObject data) {
        redisUtil.set(getRedisKey() + getExpressNo(), data.toJSONString(), getRedisCacheSeconds(), TimeUnit.SECONDS);
    }

    /** 获取快递缓存
     * @param data JSONObject 检测返回的结果
     * @author Mr.Zhang
     * @since 2020-07-06
     */
    private void checkResult(JSONObject data) {
        if (!data.getString("status").equals("0")){
            throw new HhException(data.getString("msg"));
        }
    }
}

